﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace ConfigurationManager.Model
{
    public class Instance
    {
        public int Id
        {
            get;
            set;
        }

        public string Name
        {
            get;
            set;
        }

        public string Address
        {
            get;
            set;
        }

        public string HostName
        {
            get;
            set;
        }

        public int Port
        {
            get;
            set;
        }

        public Product Product
        {
            get;
            set;
        }

        public string ProductName
        {
            get
            {
                return Product.Name;
            }
            set
            {
                Product.Name = value;
            }
        }

        public List<Model.Process> Processes
        {
            get;
            set;
        }

        public Instance()
        {
            this.Product = new Product();
            this.Processes = new List<Process>();
        }

        #region Métodos
        public static string CreateAddress(Instance instance)
        {
            return string.Format(@"net.tcp://{0}:{1}/Listener/InteligenceManagerInstance/{2}/{3}", instance.HostName, instance.Port.ToString(), instance.Product.Name, instance.Name);
        }

        public static List<Instance> Retrieve()
        {
            DataAccess.Instance i = new DataAccess.Instance();
            return i.Retrieve();
        }

        public static List<Instance> RetrieveByProduct(int productId)
        {
            DataAccess.Instance i = new DataAccess.Instance();
            return i.RetrieveByProduct(productId);
        }

        public static Instance Retrieve(int id)
        {
            DataAccess.Instance p = new DataAccess.Instance();
            return p.Retrieve(id);
        }

        public static void Save(Instance instance)
        {
            if (string.IsNullOrEmpty(instance.Name))
                throw new ValidationException("O nome da instância deve ser informado.");
            else if (instance.Name.Length > 50)
                throw new ValidationException("O nome da instância deve ter no máximo 50 caracteres.");

            if (string.IsNullOrEmpty(instance.HostName))
                throw new ValidationException("O Host Name deve ser informado.");
            else if (instance.HostName.Length > 200)
                throw new ValidationException("O Host Name deve ter no máximo 200 caracteres.");
            else if (Uri.CheckHostName(instance.HostName) == UriHostNameType.Unknown)
                throw new ValidationException("O Host Name informado é inválido.");

            if (instance.Port <= UInt16.MinValue || instance.Port > UInt16.MaxValue)
                throw new ValidationException("A porta deve estar entre 1 e 65535.");

            instance.Address = CreateAddress(instance);

            if (instance.Product.Id <= 0)
                throw new ValidationException("O produto deve ser informado.");

            DataAccess.Instance p = new DataAccess.Instance();

            if (p.VerifyNameIntegrity(instance))
                throw new ValidationException("O nome da instância informado já está em uso para o produto.");

            if (p.VerifyAddressIntegrity(instance))
                throw new ValidationException("O endereço da instância informado já está em uso.");

            p.Save(instance);
        }

        public static void Delete(int id)
        {
            VerificyDependencies(id);
            DataAccess.Instance p = new DataAccess.Instance();
            p.Delete(id);
        }

        private static void VerificyDependencies(int id)
        {
            DataAccess.Process p = new DataAccess.Process();
            int count = p.CountByInstance(id);
            if (count > 0)
                throw new ValidationException("A instância não pode ser excluída pois possui processos associados. Para excluir a instância, exclua antes os processos associados.");

        }
        #endregion
    }
}
